﻿#ifndef FCDATAPACKAGE_H
#define FCDATAPACKAGE_H
#include <QtCore/qglobal.h>
#include "FCNodeGlobal.h"
#include <QDebug>
#include <QDataStream>
#include "FCDataItem.h"
FC_IMPL_FORWARD_DECL(FCDataPackage)

/**
 * @brief DataPackage实现键值对数据的传递，其赋值操作都是引用操作，数据区并不发生拷贝
 *
 * 若要实现拷贝，需要显示调用@sa copy 函数
 */
class FCNODE_API FCDataPackage
{
    FC_IMPL(FCDataPackage)
public:
    FCDataPackage();
    ~FCDataPackage();
    //拷贝构造重载，实现弱拷贝
    FCDataPackage(const FCDataPackage& d);

    //移动构造
    FCDataPackage(FCDataPackage&& d);

    //等号操作符重载
    FCDataPackage& operator =(const FCDataPackage& a);

    //判断是否为空
    bool isNull() const;

    //拷贝
    FCDataPackage copy() const;

    //获取这个变量的id，可以看出是否共同引用一个变量
    qint64 id() const;

    //等于判断 只要id相等就认为相等
    bool operator ==(const FCDataPackage& other) const;

    //获取值
    QVariant getValue(const QString& key) const;

    //获取值对应的名字
    QString getValueName(const QString& key) const;

    //获取item
    FCDataItem getValueItem(const QString& key) const;
    void setValueItem(const QString& key, const FCDataItem& item);

    //设置值
    void setValue(const QString& key, const QVariant& v, const QString& n);

    //获取所有的值
    QList<QVariant> getValues() const;

    //获取所有的变量名
    QList<QString> getValueNames() const;

    //获取所有的key
    QList<QString> getKeys() const;

public:

    /**
     * @brief QVariant转为QString
     *
     * 此转换会以尽量可以明文的形式把QVariant转换为字符串，有些如QByteArray，无法用明文的，会转换为Base64进行保存
     * @param var QVariant值
     * @return 转换好的字符串
     * @see stringToVariant
     */
    static QString variantToString(const QVariant& var);

    /**
     * @brief variantToString的逆方法
     * @param var 字面值
     * @param typeName 参数类型
     * @return 根据字面值转换回来的QVariant
     */
    static QVariant stringToVariant(const QString& var, const QString& typeName);

    /**
     * @brief 把QVariant转换为Base64字符
     * @param var
     * @return
     */
    template<typename T>
    static QString converVariantToBase64String(const QVariant& var)
    {
        if (var.canConvert<T>()) {
            QByteArray byte;
            QDataStream st(&byte, QIODevice::ReadWrite);
            T ba = var.value<T>();
            st << ba;
            return (QString(byte.toBase64()));
        }
        return (QString());
    }


    /**
     * @brief 把Base64字符转换为对应变量
     * @param base64
     * @return
     */
    template<typename T>
    static QVariant converBase64StringToVariant(const QString& base64)
    {
        QByteArray byte = QByteArray::fromBase64(base64.toLocal8Bit());
        QDataStream st(&byte, QIODevice::ReadWrite);
        T ba;

        st >> ba;
        return (QVariant::fromValue(ba));
    }
};

#endif // FCDATAPACKAGE_H
